import { Address, beginCell, toNano, fromNano, } from '@ton/core';
import { Router } from '../wrappers/Router';
import { Pool } from '../wrappers/Pool';
import { NetworkProvider } from '@ton/blueprint';
import { MyJettonMaster } from '../wrappers/MyJetton_MyJettonMaster';
import { MyJettonWallet } from '../wrappers/MyJetton_MyJettonWallet';

const tspa = "kQCrJ-ArHG3LoX_b9Wz7hLVSNeR0_Cz2hSUwashWDavq-r4P";
const tusdt = "kQCymv2MvB5Bb2Jd45D92HaUfmf06CBm-LJMFU7qjeSjX0V3";

const tspa_owner = "kQBhxrSFHGrvX1g5tubQbuePKvBBMtUMxnUMJRxBKjcTKUFd";
const tusdt_owner = "kQBBO0nvoLTgrW2zWRV_MphUUpcuSlAXpDXxXx0y4NsfB8W7";
const jetton_owner = "0QCjPTREUgXS0n1DxX3-clRKW6NIKp5zF8kxoGkYV2b229sN";

const jetton_to = "0QCSSOrjsJdYJZXPTJbfNQ8wZsoycmWdBagwTzYE3ztmjxQE";

const master_in = tusdt;
const master_out = tspa;
const router = "EQBW4Cnl4ZspBRneKZgbf9CCMnUCvmNyLnq5anEULY4rOWey";

const ownerAddress = Address.parse(jetton_owner);
const masterAAddress = Address.parse(master_in);
const masterBAddress = Address.parse(master_out);

const current_id = 2;
const swap_price = 33_333_000 / 1000;

const pool = "";

export async function run(provider: NetworkProvider) {
    //await deploy(provider);
    //await pendingOrder(provider);
    await swap(provider);
}

export async function deploy(provider: NetworkProvider) {
    const myRouter = provider.open(await Router.fromInit(ownerAddress));
    
    const masterA = provider.open(
        MyJettonMaster.fromAddress(masterAAddress),
    );
    const masterB = provider.open(
        MyJettonMaster.fromAddress(masterBAddress),
    );

    const walletA = await masterA.getGetWalletAddress(myRouter.address);
    const walletB = await masterB.getGetWalletAddress(myRouter.address);
    
    console.log("A: "+walletA);
    console.log("B: "+ walletB);

    await myRouter.send(
        provider.sender(),
        {
            value: toNano('0.05'),
        },
        {
            $$type: 'Deploy',
            queryId: 0n,
            walletA: walletA,
            walletB: walletB,
        }
    );

    await provider.waitForDeploy(myRouter.address);
}

// 挂单
async function pendingOrder(provider: NetworkProvider) {
    const senderAddress = provider.sender()?.address;
    if (!senderAddress) {
        throw new Error('Sender address is undefined.');
    }
    const masterA = provider.open(
        MyJettonMaster.fromAddress(masterAAddress),
    );
    const masterB = provider.open(
        MyJettonMaster.fromAddress(masterBAddress),
    );
    // let in_amount = msg.amount * self.price / 100_000_000; in tact
    // outAmount = inAmount * 100_000_000 / swap_price; in ts
    
    const amountA = 1_000_000 * 2; // usdt
    const amountB = amountA * 100_000_000 / swap_price / 1_000_000_000; // spa 
    console.log("amountB: "+amountB);
    
    const master = masterA;
    const transJettonAmount = toNano("0.005");
    const forwardTonAmt = toNano(0.05);
    
    let jettonWalletAddress = await master.getGetWalletAddress(senderAddress);
    const srcWallet = provider.open(
        MyJettonWallet.fromAddress(jettonWalletAddress),
    );
    console.log('source address: '+senderAddress);
    
    const forwardTargetAddress = Address.parse(jetton_to);
    const targetAddress = Address.parse(router);
    const targetJettonWalletAddress = await master.getGetWalletAddress(targetAddress);
    const targetJettonWallet = provider.open(
        MyJettonWallet.fromAddress(targetJettonWalletAddress),
    );
    console.log('target address: '+ targetJettonWalletAddress);
    
    /*
     * 第一次jetton转账之前,无法查询jetton余额.因为jetton wallet未部署.
    const walletDataBefore = await targetJettonWallet.getGetWalletData();
    const balanceBefore = walletDataBefore.balance;
    console.log('Current balance:' + fromNano(balanceBefore));
    */

    const nanoTransfer = transJettonAmount;
    const forwardNano = forwardTonAmt;
    
    const id = current_id;
    const price = BigInt(swap_price);
    
    const myPool = Pool.fromInit(targetAddress, BigInt(id));
    console.log("pool:"+myPool);

    const forwardPayload = beginCell()
        .storeUint(1,1)
        .storeRef(
            beginCell()
            .storeUint(id, 32)
            .storeUint(price, 16)
            .endCell()
        ).endCell().beginParse();
    
    await srcWallet.send(
        provider.sender(),
        {
            value: toNano('0.1'),
            // sendMode: SendMode.PAY_GAS_SEPARATELY, fixed 
        },
        {
            $$type: 'JettonTransfer',
            query_id: 101n,
            destination: targetAddress,
            response_destination: senderAddress,
            amount: nanoTransfer,
            custom_payload: beginCell().endCell(),
            forward_ton_amount: forwardNano,
            forward_payload: forwardPayload,
        }
    );

    console.log(`Transfer ${transJettonAmount} to ${targetAddress} and waiting 22s...`);
    await new Promise((resolve) => setTimeout(resolve, 22000));

    const walletDataAfter = await targetJettonWallet.getGetWalletData();
    const balanceAfter = walletDataAfter.balance;
    console.log('Current balance:' + fromNano(balanceAfter));
}

// 交换
async function swap(provider: NetworkProvider) {
    const senderAddress = provider.sender()?.address;
    if (!senderAddress) {
        throw new Error('Sender address is undefined.');
    }
    const masterA = provider.open(
        MyJettonMaster.fromAddress(masterAAddress),
    );
    const masterB = provider.open(
        MyJettonMaster.fromAddress(masterBAddress),
    );
    // let in_amount = msg.amount * self.price / 100_000_000; in tact
    // outAmount = inAmount * 100_000_000 / swap_price; in ts
    
    const amountA = 1_000_000 * 2; // usdt
    const amountB = amountA * 100_000_000 / swap_price / 1_000_000_000; // spa 
    console.log("amountB: "+amountB);
    
    const master = masterB;
    const transJettonAmount = toNano(amountB);
    const forwardTonAmt = toNano(0.05);
    
    let jettonWalletAddress = await master.getGetWalletAddress(senderAddress);
    const srcWallet = provider.open(
        MyJettonWallet.fromAddress(jettonWalletAddress),
    );
    console.log('source address: '+senderAddress);
    
    const forwardTargetAddress = Address.parse(jetton_to);
    const targetAddress = Address.parse(router);
    const targetJettonWalletAddress = await master.getGetWalletAddress(targetAddress);
    const targetJettonWallet = provider.open(
        MyJettonWallet.fromAddress(targetJettonWalletAddress),
    );
    console.log('target address: '+ targetJettonWalletAddress);
    
    /*
     * 第一次jetton转账之前,无法查询jetton余额.因为jetton wallet未部署.
    const walletDataBefore = await targetJettonWallet.getGetWalletData();
    const balanceBefore = walletDataBefore.balance;
    console.log('Current balance:' + fromNano(balanceBefore));
    */

    const nanoTransfer = transJettonAmount;
    const forwardNano = forwardTonAmt;
    
    const id = current_id;

    const myPool = Pool.fromInit(targetAddress, BigInt(id));
    console.log("pool:"+myPool);

    const forwardPayload = beginCell()
        .storeUint(1,1)
        .storeRef(
            beginCell()
            .storeUint(id, 32)
            .endCell()
        ).endCell().beginParse();
    
    await srcWallet.send(
        provider.sender(),
        {
            value: toNano('0.1'),
            // sendMode: SendMode.PAY_GAS_SEPARATELY, fixed 
        },
        {
            $$type: 'JettonTransfer',
            query_id: 101n,
            destination: targetAddress,
            response_destination: senderAddress,
            amount: nanoTransfer,
            custom_payload: beginCell().endCell(),
            forward_ton_amount: forwardNano,
            forward_payload: forwardPayload,
        }
    );

    console.log(`Transfer ${transJettonAmount} to ${targetAddress} and waiting 22s...`);
    await new Promise((resolve) => setTimeout(resolve, 22000));

    const walletDataAfter = await targetJettonWallet.getGetWalletData();
    const balanceAfter = walletDataAfter.balance;
    console.log('Current balance:' + fromNano(balanceAfter));
}